package org.jeecg.modules.simulator.model.line.plan;

import lombok.Setter;
import org.jeecg.modules.simulator.model.train.action.TrainActionRecorders;
import org.jeecg.modules.simulator.model.train.timeplan.PlanTableItem;
import org.jeecg.modules.simulator.model.train.timeplan.TrainPlanTable;
import org.jeecg.modules.simulator.util.TimeUtil;
import lombok.Getter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * @program: gp
 * @description:
 * @author: lydms
 * @create: 2024-08-07 14:41
 **/
public class TrainPlanTablePath extends LinkedList<TrainPlanTable>  {





    @Getter
    private final    String lineId;
    private Map<String, TrainPlanTable> trainPlanTableNameMap;
    private Map<String,String> directionStrMap;
    private Map<Integer, PlanTableItem> planTableItemMap;
    @Getter
    private final String trainId;
    @Getter
    private final String firstStationName;
    @Getter
    private final  String firstationId;
    @Getter
    private  final  String lastStationName;
    @Getter
    private  final  String firstTime;
    @Getter
    private final String lastTime;
    public TrainPlanTablePath(String lineId, List<TrainPlanTable> trainPlanTableList, String trainid) {
        super(trainPlanTableList);
        this.lineId = lineId;
        this.trainId = trainid;
        this.trainPlanTableNameMap = new HashMap<>();
        this.directionStrMap=new HashMap<>();
        Collections.sort(this);
        this.planTableItemMap=new HashMap<>();
        this.firstStationName=trainPlanTableList.get(0).getArriveStaionName();
        this.firstationId=trainPlanTableList.get(0).getArrivateStaionId();
        this.lastStationName=trainPlanTableList.get(trainPlanTableList.size()-1).getArriveStaionName();

        this.firstTime=trainPlanTableList.get(0).getArriveTime();
        this.lastTime=trainPlanTableList.get(trainPlanTableList.size()-1).getDepartTime();

        for(int i=1;i<trainPlanTableList.size();i++){

            PlanTableItem  stationitem= setStationItem(trainPlanTableList.get(i-1));

            planTableItemMap.put(i*2-1,stationitem);
            PlanTableItem sectitem=setSectItem(trainPlanTableList.get(i-1),trainPlanTableList.get(i));
            planTableItemMap.put(i*2,sectitem);

            stationitem.setVid(sectitem.getId());

            this.trainPlanTableNameMap.put(trainPlanTableList.get(i).getArriveStaionName(), trainPlanTableList.get(i-1));


            if(i!=trainPlanTableList.size()-1){
                String value=trainPlanTableList.get(i).getArriveStaionName()+"-"+trainPlanTableList.get(i+1).getArriveStaionName();
                directionStrMap.put(trainPlanTableList.get(i).getArriveStaionName(),value);
            }else {
                PlanTableItem  stationitem1= setStationItem(trainPlanTableList.get(trainPlanTableList.size()-1));
                stationitem1.setVid(trainPlanTableList.get(trainPlanTableList.size()-2).getArrivateStaionId()+"-"+trainPlanTableList.get(trainPlanTableList.size()-1).getArrivateStaionId());
                planTableItemMap.put(trainPlanTableList.size()*2-1,stationitem1);
                String value="end";
                directionStrMap.put(trainPlanTableList.get(i).getArriveStaionName(),value);
            }
        }





    }


    /**
     * @description:设定区间要素
     *
     * @author: renzhg
     * @date: 2024/7/29 14:12
     **/
    private PlanTableItem setSectItem(TrainPlanTable firstTrainPlanTable,TrainPlanTable  secondTrainPlanTable){
        PlanTableItem planTableItemsect=new PlanTableItem();
        planTableItemsect.setArrivalTime(firstTrainPlanTable.getDepartTime());
        planTableItemsect.setDepartureTime(secondTrainPlanTable.getArriveTime());
        planTableItemsect.setName(firstTrainPlanTable.getArriveStaionName()+"-"+secondTrainPlanTable.getArriveStaionName());
        planTableItemsect.setId(firstTrainPlanTable.getArrivateStaionId()+"-"+secondTrainPlanTable.getArrivateStaionId());
        planTableItemsect.setVid(firstTrainPlanTable.getArrivateStaionId()+"-"+secondTrainPlanTable.getArrivateStaionId());
        planTableItemsect.setType("sect");
        try {
            planTableItemsect.setDuring(calculateTimeDifference2(firstTrainPlanTable.getDepartTime(),secondTrainPlanTable.getArriveTime()));
        }catch (Exception e){
            e.printStackTrace();
            planTableItemsect.setDuring(-1);
        }
        return planTableItemsect;
    }
    /**
     * @description:设定站点要素
     *
     * @author: renzhg
     * @date: 2024/7/29 14:13
     **/
    private PlanTableItem setStationItem(TrainPlanTable trainPlanTable) {
        PlanTableItem planTableItemstation=new PlanTableItem();
        planTableItemstation.setId(trainPlanTable.getArrivateStaionId());

        planTableItemstation.setName(trainPlanTable.getArriveStaionName());
        planTableItemstation.setArrivalTime(trainPlanTable.getArriveTime());
        planTableItemstation.setDepartureTime(trainPlanTable.getDepartTime());
        planTableItemstation.setDuring(trainPlanTable.getRemainTime());
        planTableItemstation.setType("station");
        return  planTableItemstation;

    }


    /**
     * 计算两个时间字符串之间的时间差（以秒为单位）。
     *
     * @param time1 第一个时间字符串，格式为 "HH:mm:ss"
     * @param time2 第二个时间字符串，格式为 "HH:mm:ss"
     * @return 时间差（以秒为单位）
     * @throws ParseException 如果时间字符串无法解析
     */
    public  int calculateTimeDifference(String time1, String time2) throws ParseException {
        // 定义时间格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 解析时间字符串为 Date 对象
        Date date1 = sdf.parse(time1);
        Date date2 = sdf.parse(time2);
        // 计算时间差（毫秒）
        long differenceInMillis = date1.getTime() - date2.getTime();

        // 转换为秒
        return (int) (differenceInMillis / 1000);
    }
    public  int calculateTimeDifference2(String time1, String time2) throws ParseException {
        // 定义时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");

        // 解析时间字符串为LocalTime对象
        LocalTime localTime1 = LocalTime.parse(time1, formatter);
        LocalTime localTime2 = LocalTime.parse(time2, formatter);

        // 计算时间差并返回秒数
        return (int)Math.abs(ChronoUnit.SECONDS.between(localTime1, localTime2));
    }








    //判读一个时间点是否在站点的到达时间和离站时间之间
    public boolean isTimePointInStationTime(String timePt, String stationName) {
        TrainPlanTable trainPlanTable = this.trainPlanTableNameMap.get(stationName);
        if (trainPlanTable == null) {
            return false;
        }
        try {
            int diff1 = calculateTimeDifference(timePt, trainPlanTable.getArriveTime());
            int diff2 = calculateTimeDifference(timePt, trainPlanTable.getDepartTime());
            return diff1 >= 0 && diff2 <= 0;
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }
    }

    //找出最近到达时间点的车辆
    public int getNearestArriveTimePoint(String timePt, String stationName) {
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < this.size(); i++) {
            int diff = Integer.MAX_VALUE;
            try {
                if(this.get(i).getArriveStaionName().equals(stationName)) {
                    LocalTime arrivetm = TimeUtil.convertStringToLocalTime(this.get(i).getArriveTime());
                    LocalTime timpt = TimeUtil.convertStringToLocalTime(timePt);
                    //arrivetm在timpt之后
                    if (TimeUtil.compareLocalTimes(timpt, arrivetm) == 2) {
                        diff = Math.abs(calculateTimeDifference(timePt, this.get(i).getArriveTime()));
                    }
                }

            } catch (ParseException e) {
                e.printStackTrace();
            }
            if (diff < min) {
                min = diff;
            }
        }
        return min;
    }






    public Map<Integer,PlanTableItem> getPlanTableItemMap(){
        return planTableItemMap;
    }

    public void plan2TrainActionRecords(TrainActionRecorders trainActions) {
        trainActions.getTrainActionRecordMap();

    }









    public TrainPlanTable findTrainPlanTable(String StationName) {
        return trainPlanTableNameMap.get(StationName);
    }
    public String findTrainDirectionStr(String StationName) {
        return directionStrMap.get(StationName);
    }
}
